class UsersController < LockDownController
  include LockDown::Session::Access

  LockDown::ROLES.each do |key,value|
    define_method("list_#{Inflector.pluralize(key.to_s)}") { list_users(value) }
    define_method("new_#{key.to_s}") { new_user(value) }
    define_method("show_#{key.to_s}") { show_user(value) }
    define_method("edit_#{key.to_s}") { edit_user(value) }
    define_method("create_#{key.to_s}") { create_user(value) }
    define_method("update_#{key.to_s}") { update_user(value) }
    define_method("delete_#{key.to_s}") { delete_user(value) }
  end

  private
    #
    # The @pager is a Flipper pager
    #
    def list_users(role)
      @pager, @users = User.pagination_find(params,:searchby_fields => ["users.first_name",
                                                                        "users.last_name",
                                                                        "users.login"],
                                                   :order => "last_name",
                                                   :list_url => "/users/" + list_method_from(role),
                                                   :conditions => "users.role_id = #{role}")
      render(:partial => "list", :layout => @layout , :locals => {:role => role })
    end
    
    def new_user(role)
      @user = User.new
      @user.role_id = role
      @user.reset_password = true
      
      render(:partial => "form", :layout => @layout , 
              :locals => {:form_title => form_title(role), 
              :form_action => form_action(role),
              :btn_action => btn_action(role),
              :list_method => list_method_from(@user.role.id)})
    end
    
    def show_user(role)
      get_user(role)
      if @user.nil?
        redirect_to(denied_url) 
        return
      else
        render(:partial => "show", :layout => @layout, 
               :locals => {:form_title => "Showing #{role_title(role)} id: #{@user.id}",
               :update_method => update_method_from(@user.role.id),
               :list_method => list_method_from(@user.role.id)})
      end
    end
    
    def edit_user(role)
      update_user_from_post(role)
      case params[:commit]
      when "Cancel"
        redirect_to(:action => list_method_from(role))
        return
      when "Change Password"
        @user.reset_password = true
      when "Add Address"
        #no special action required. just need to render the form again
        #the update_user_from_post takes care of the address addition
      else
        if save_user?(role)
          store_session_user(@user) if current_user_id == @user.id
          reset_permissions_from_login
          if params[:commit] == "Accept and Update"
            @user.profile.viewed = true
            @user.profile.accepted_by = current_updater_id
            @user.profile.updated_by = current_updater_id
            @user.profile.save
          end
          flash[:notice] = "User successfully updated"
          redirect_to(:action => show_method_from(@user.role_id), :id => @user.id)
          return
        end
      end
    
      if @user.nil?
        redirect_to(denied_url) 
        return
      end
      
      render(:partial => "form", :layout => @layout , 
              :locals => {:form_title => form_title(role), 
              :form_action => form_action(role),
              :btn_action => btn_action(role),
              :list_method => list_method_from(@user.role.id)})
    end

    def create_user(role)
      case request.method
      when :post
        case params[:commit]
        when "Cancel"
          redirect_to(:action => list_method_from(role))
          return
        else
          create_user_from_post(role)
          if save_user?(role)
            flash[:notice] = "User successfully created"
            redirect_to(:action => show_method_from(role), :id => @user.id)
            return
          else
            @user.reset_password = true
            @user.password = nil
            @user.password_confirmation = nil
          end
        end
      else
        new_user(role)
      end
      render(:partial => "form", :layout => @layout , 
           :locals => {:form_title => form_title(role), 
                        :form_action => form_action(role),
                        :btn_action => btn_action(role),
                        :list_method => list_method_from(@user.role.id)})
    end


    def save_user?(role)
      #Errors may have been entered in the additional user information:
      #contacts and addresses
      return unless @user.errors.empty?

      #Run validation on user object first...don't want to create
      #updater if user info is invalid
      return false unless @user.valid?
      
      updater = update_updater
      if updater.save
        @user.updater_id = updater.id
        u_by = updater.id
        u_by = current_updater_id if current_updater_id > 0
        @user.updated_by = u_by
        if @user.save
          if updater.user_id != @user.id
            updater.user_id = @user.id
            updater.save
          end
          return true
        end
      end
      return false
    rescue Exception => e
      logger.error("Error saving user: #{e}")
      raise
    end

    def update_updater
      updater_name =  @user.first_name + " " + @user.last_name
      return Updater.new(:name => updater_name) unless @user.id

      updater = Updater.find(@user.updater_id)
      updater.name = updater_name
      return  updater
    end


    def create_user_from_post(role)
      @user = User.new
      @user.role_id = role
      @user.reset_password = false
      gather_user_groups_from_post
    end

    def update_user_from_post(role)
      @user = User.find(:first, :conditions => ["id = ? and role_id = ?",
                        params[:user][:id].to_i, role])
      if @user.nil?
        redirect_to(denied_url) 
        return
      end
      gather_user_groups_from_post
    end

    def delete_user(role)
      get_user(role)
      if @user.nil?
        redirect_to(denied_url) 
        return
      else
        @user.destroy
        redirect_to(:action => list_method_from(role))
      end
    end

    def get_user(role)
      @user = User.find(:first, :conditions => ["id = ? and role_id = ?", id_param , role])
    end
    
    def show_method_from(role)
      "show_#{LockDown.role_name(role)}"
    end

    def list_method_from(role)
      "list_#{LockDown.role_name(role)}s"
    end

    def update_method_from(role)
      "update_#{LockDown.role_name(role)}"
    end

    def form_title(role)
      return "My Account" if @user && @user.id == current_user_id
      return "Updating #{role_title(role)} id: #{@user.id}" if @user.id
      "Creating #{LockDown.role_name(role)}"
    end

    def form_action(role)
      return "/users/update_#{LockDown.role_name(role)}" if @user.id
      "/users/create_#{LockDown.role_name(role)}"
    end

    def btn_action(role)
      return "Update" if @user.id
      "Create"
    end
    
    def gather_user_groups_from_post
      #clear orphans
      ugroups = @user.user_group.dup
      ugroups.each do |usr_grp|
        @user.user_group.delete(usr_grp) unless param?("grp_#{usr_grp.id}")
      end

      params.each do |key,value|
        if key =~ /^grp_/
          grp_id = get_id_from_param(key)
          @user.user_group << UserGroup.find(grp_id) unless @user.has_user_group_id?(grp_id)
        end
      end
    end
end
